
package com.hlkj.pay.controller.pay.helibao;

import java.util.*;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.ext.impl.helipay.dto.HeliPayMccDto;
import com.hlkj.pay.controller.pay.OneLevelDictListener;
import com.hlkj.pay.infrastructure.model.pay.PayChannelDictDO;

/**
 * @author HlpayTeam
 * @date 2024/09/25 9:54
 */
public class HelibaoCategoryDictListener extends AnalysisEventListener<HelibaoCategory> {

    private static final Logger LOGGER = LoggerFactory.getLogger(OneLevelDictListener.class);

    /**
     * 每隔5条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 5;

    List<HelibaoCategory> list = new ArrayList<>();

    private String channelCode;

    private String dictKey;

    /**
     * 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */

    public HelibaoCategoryDictListener(String channelCode, String dictKey) {
        this.channelCode = channelCode;
        this.dictKey = dictKey;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data
     *            one row value. Is is same as
     *            {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(HelibaoCategory data, AnalysisContext context) {
        // LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (list.size() >= BATCH_COUNT) {
            // processSql();
            // 存储完成清理 list
            // list.clear();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        LOGGER.info("所有数据解析完成！");
        processSql();
    }

    public void processSql() {
        // List<PayChannelDictDO> payChannelDictList = new ArrayList<>();
        int oneLevel = 0;
        Map<String, String> oneLevelDict = new HashMap<>();
        Map<String, List<HelibaoCategory>> collect = list.stream().collect(Collectors.groupingBy(helibaoCategory -> helibaoCategory.getOneCategory()));
        for (Map.Entry<String, List<HelibaoCategory>> entryL : collect.entrySet()) {
            Map<String, String> twoLevelDict = new HashMap<>();
            Map<String, String> thirdLevelDict = new HashMap<>();
            Map<String, Integer> twoLevelKey = new HashMap<>();
            Map<String, Integer> oneLevelKey = new HashMap<>();
            Set<String> dictSql = new HashSet<>();
            List<PayChannelDictDO> payChannelDictList = new ArrayList<>();
            for (HelibaoCategory helibaoCategory : entryL.getValue()) {
                PayChannelDictDO endDayChannelDictDO = new PayChannelDictDO();
                String oneCategory = helibaoCategory.getOneCategory();
                String category = helibaoCategory.getCategory();
                endDayChannelDictDO.setField2(category);
                String mcc = helibaoCategory.getMcc();
                if (mcc != null && mcc.contains("[")) {
                    List<String> strings = JsonUtils.parseArray(mcc, String.class);
                    if (strings.size() > 0) {
                        mcc = strings.get(0);
                    }
                }
                if (!oneLevelDict.containsKey(oneCategory)) {
                    oneLevel = oneLevel + 1;
                    oneLevelDict.put(oneCategory, String.format("%02d", oneLevel));
                    oneLevelKey.put(String.format("%02d", oneLevel), 0);
                    PayChannelDictDO payChannelDictDO = new PayChannelDictDO();
                    payChannelDictDO.setDictLevel(1);
                    payChannelDictDO.setDictValue(oneLevelDict.get(oneCategory));
                    payChannelDictDO.setDictDesc(oneCategory);
                    payChannelDictList.add(payChannelDictDO);
                }
                HeliPayMccDto heliPayMccDto = new HeliPayMccDto();
                heliPayMccDto.setMerchantType(helibaoCategory.getMerchantType());
                heliPayMccDto.setMerchantCategory(helibaoCategory.getMerchantCategory());
                heliPayMccDto.setMcc(mcc);
                if (category.contains("-")) {
                    category = category.replace(oneCategory + "-", "");
                }
                String[] split = category.split("-");
                for (int i = 0; i < split.length - 1; i++) {
                    String parentDictKey = oneCategory;
                    if (i > 0) {
                        parentDictKey = split[i - 1];
                    }
                    String dictKey = split[i];
                    switch (i) {
                        case 1:
                            if (!thirdLevelDict.containsKey(dictKey)) {
                                PayChannelDictDO payChannelDictDO = new PayChannelDictDO();
                                payChannelDictDO.setDictLevel(3);
                                payChannelDictDO.setParentDictKey(twoLevelDict.get(parentDictKey));
                                Integer i1 = twoLevelKey.get(twoLevelDict.get(parentDictKey));
                                if (i1 == null) {
                                    i1 = 0;
                                }
                                twoLevelKey.put(twoLevelDict.get(parentDictKey), i1 + 1);
                                payChannelDictDO.setDictValue(twoLevelDict.get(parentDictKey) + String.format("%02d", i1 + 1));
                                thirdLevelDict.put(dictKey, payChannelDictDO.getDictValue());
                                payChannelDictDO.setDictDesc(split[i]);
                                payChannelDictList.add(payChannelDictDO);
                            }
                            break;
                        case 0:
                            if (!twoLevelDict.containsKey(dictKey)) {
                                PayChannelDictDO payChannelDictDO = new PayChannelDictDO();
                                payChannelDictDO.setDictLevel(2);
                                payChannelDictDO.setParentDictKey(oneLevelDict.get(parentDictKey));
                                payChannelDictDO.setDictValue(split[i]);

                                Integer i1 = oneLevelKey.get(oneLevelDict.get(parentDictKey));
                                if (i1 == null) {
                                    i1 = 0;
                                }
                                oneLevelKey.put(oneLevelDict.get(parentDictKey), i1 + 1);
                                payChannelDictDO.setDictValue(oneLevelDict.get(parentDictKey) + String.format("%02d", i1 + 1));
                                twoLevelDict.put(dictKey, payChannelDictDO.getDictValue());
                                payChannelDictDO.setDictDesc(split[i]);
                                payChannelDictList.add(payChannelDictDO);
                            }
                            break;

                    }
                }
                Integer length = split.length;

                endDayChannelDictDO.setDictValue(helibaoCategory.getCode());
                endDayChannelDictDO.setDictDesc(split[length - 1]);
                endDayChannelDictDO.setDictLevel(length + 1);
                String parentDictKey = oneCategory;
                switch (length) {
                    case 3:
                        parentDictKey = split[length - 2];
                        endDayChannelDictDO.setParentDictKey(thirdLevelDict.get(parentDictKey));
                        break;
                    case 2:
                        parentDictKey = split[length - 2];
                        endDayChannelDictDO.setParentDictKey(twoLevelDict.get(parentDictKey));
                        break;
                    case 1:
                        endDayChannelDictDO.setParentDictKey(oneLevelDict.get(parentDictKey));
                        break;
                }
                endDayChannelDictDO.setField1(JsonUtils.toJsonString(heliPayMccDto));
                payChannelDictList.add(endDayChannelDictDO);
            }
            // System.out.println(entryL.getKey());
            // System.out.println("========================================");
            payChannelDictList.stream().forEach(payChannelDictDO -> {
                // 一级
                StringBuilder parentSb = new StringBuilder(
                        "insert into t_pay_channel_dict(channel_code,dict_key,parent_dict_key,dict_level,dict_value,dict_desc,field1,field2) value (");
                parentSb.append("'");
                parentSb.append(channelCode);
                parentSb.append("','");
                parentSb.append(dictKey);
                parentSb.append("','");
                parentSb.append(payChannelDictDO.getParentDictKey());
                parentSb.append("',");
                parentSb.append(payChannelDictDO.getDictLevel());
                parentSb.append(",'");
                parentSb.append(payChannelDictDO.getDictValue());
                parentSb.append("','");
                parentSb.append(payChannelDictDO.getDictDesc());
                parentSb.append("','");
                parentSb.append(payChannelDictDO.getField1());
                parentSb.append("','");
                parentSb.append(payChannelDictDO.getField2());
                parentSb.append("');");
                dictSql.add(parentSb.toString());

            });
            dictSql.stream().forEach(sql -> {
                System.out.println(sql);
            });
        }
    }
}
